package dao;

import org.hibernate.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.io.Serializable;


/**
 * User: gutnikov
 * Date: 09.09.2010
 */
@Transactional
public class HibernateDaoImpl<T> implements HibernateDao<T> {

	@Autowired
	protected SessionFactory sessionFactory;

	private final Class<T> modelClass;

	public HibernateDaoImpl() {
		modelClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	public HibernateDaoImpl(Class<T> modelClass) {
		this.modelClass = modelClass;
	}

	protected SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	@Required
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}


	@Transactional
	public T getModel(Serializable id) {
		Session sess = getSession();
		return (T) sess.get(modelClass, id);
	}

	public Criteria createCriteria() {
		Session sess = sessionFactory.getCurrentSession();
		return sess.createCriteria(modelClass);
	}

	public Query createQuery(String hql) {
		Session sess = sessionFactory.getCurrentSession();
		return sess.createQuery(hql);
	}

	public SQLQuery createSQLQuery(String sql) {
		Session sess = sessionFactory.getCurrentSession();
		return sess.createSQLQuery(sql);
	}

	protected T load( Serializable id) {
		Session sess = getSession();
		return (T) sess.load(modelClass, id);
	}

	@Transactional(isolation = Isolation.SERIALIZABLE)
	public void save( T model) {
		Session sess = getSession();
		sess.save(model);
		sess.flush();
	}

	@Transactional
	public void update( T model) {
		Session sess = getSession();
		sess.update(model);
	}

	@Transactional
	public void delete( T model) {
		Session sess = getSession();
		sess.delete(model);
	}

	@Transactional
	public T getById( Serializable id) {
		return load(id);
	}
}

